{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Naive Bayes\n",
    "这个 ipynb 使用 Naive Bayes 完成 Spam Detection 任务。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数据导入初始化\n",
    "import os\n",
    "import re\n",
    "import random\n",
    "import numpy as np \n",
    "\n",
    "# 数据集介绍\n",
    "'''\n",
    "这里使用的数据集是 Ling-Spam Dataset 的子集，包含 867 条 training emails 和 291 条 testing emails. Spam 的名字统一命名为 'spmsg*.txt'.\n",
    "每个文件的头两行是标题，第三行开始是内容。\n",
    "'''\n",
    "\n",
    "# 数据导入\n",
    "test_data = []\n",
    "train_data = []\n",
    "def DataLoader(path, L):\n",
    "    # 获取文件下所有的文件名\n",
    "    files = os.listdir(path)\n",
    "        \n",
    "    for filename in files:\n",
    "        filename = path+'/' + filename\n",
    "        with open(filename,'r') as f:\n",
    "            # 1 代表 Spam, 0 代表非 Spam\n",
    "            label = 1 if re.match('(.*)spmsg(.*).txt',filename) != None else 0\n",
    "#             print(filename,label)\n",
    "            L.append((f.read(),label))\n",
    "    \n",
    "test_path = 'hw4_nb/test-mails'\n",
    "train_path = 'hw4_nb/train-mails'\n",
    "DataLoader(train_path, train_data)\n",
    "DataLoader(test_path, test_data)\n",
    "# 打乱顺序\n",
    "random.shuffle(train_data)\n",
    "random.shuffle(test_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "label:\t0\n",
      "\n",
      "mail:\tSubject: references in slavic syntax\n",
      "\n",
      "dear linguists , i am going to write a coursework in syntax on government and binding grammar basis . i have preliminary chosen two topics : \" formation of yes - no questions in russian \" or \" double negation in russian \" ( like \" he does not eat nothing \" ) . could you send me some references on these two topics so that i could read the relevant literature and choose one of the topics . i would prefer references on yes-no question formation and double negation in slavic languages but any references on these topics will do , preferred are references in gb framework . thank you , elena rudnitskaya .\n",
      "\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 查看读取的文件\n",
    "print('label:\\t%s\\n' % train_data[24][1])\n",
    "print('mail:\\t%s\\n' % train_data[24][0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 移除标点符号\n",
    "算法第一步，移除所有的标点符号。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import reduce\n",
    "def RemoveTokens(data):\n",
    "    L = []\n",
    "    for mail, label in data:\n",
    "        L.append([list(filter(None,re.split('[^a-zA-Z]+',mail))),label])\n",
    "    return L\n",
    "\n",
    "train_data = RemoveTokens(train_data)\n",
    "test_data = RemoveTokens(test_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[['Subject', 're', 'sum', 'walloon', 'several', 'weeks', 'ago', 'i', 'posted', 'a', 'passage', 'in', 'the', 'local', 'walloon', 'of', 'the', 'bastogne', 'area', 'of', 'belgium', 'and', 'asked', 'for', 'a', 'translation', 'i', 'had', 'quite', 'a', 'number', 'of', 'responses', 'and', 'it', 'appears', 'that', 'the', 'responders', 'had', 'a', 'good', 'time', 'wrestling', 'with', 'the', 'passage', 'here', 'is', 'the', 'passage', 'i', 'gn', 'e', 'a', 'po', 'pre', 's', 'kinze', 'ans', 'du', 'd', 'ci', 'dj', 'asto', 'amon', 'albe', 'rt', 'le', 'yona', 'rd', 'e', 't', 'dj', 'rawa', 'rdo', 'pace', 'k', 'on', 'm', 'avot', 'dit', 'k', 'ou', 'profe', 'sseu', 'r', 'do', 'se', 'mine', 're', 'vlot', 'nos', 've', 'y', 'po', 'pa', 'rler', 'do', 'walon', 'dju', 'm', 'sovin', 'co', 'k', 'dj', 'e', 'dmande', 'a', 'c', 'momint', 'la', 'kin', 'a', 'dje', 'k', 'il', 'e', 'don', 'c', 'cure', 'la', 'dj', 'e', 'vite', 'avou', 'compris', 'k', 'i', 'n', 'astot', 'nin', 'pus', 'cure', 'k', 'mi', 'surtout', 'cand', 'dj', 'l', 'e', 've', 'you', 'avou', 'oune', 'be', 'le', 'djon', 'ne', 'bwe', 'ce', 'le', 'ki', 'n', 'compurdot', 'we', 're', 'lu', 'walon', 'me', 's', 'k', 'astot', 'bin', 'de', 'cide', 'a', 'l', 'aprinde', 'avou', 'de', 's', 'profe', 'sseu', 'rs', 'come', 'pierrot', 'come', 'jeannot', 'come', 'roger', 'ou', 'come', 'mi', 'di', 'st', 'i', 'l', 'fou', 'and', 'here', 'is', 'the', 'consensus', 'translation', 'il', 'y', 'a', 'a', 'peu', 'pre', 's', 'quinze', 'ans', 'd', 'ici', 'j', 'e', 'tais', 'chez', 'albert', 'le', 'onard', 'et', 'j', 'attendais', 'parce', 'qu', 'on', 'm', 'avait', 'dit', 'qu', 'un', 'professeur', 'du', 'se', 'minaire', 'voulait', 'nous', 'voir', 'pour', 'parler', 'du', 'wallon', 'je', 'me', 'souviens', 'ce', 'que', 'j', 'ai', 'demande', 'a', 'ce', 'moment', 'la', 'quel', 'a', 'ge', 'a', 't', 'il', 'donc', 'ce', 'cure', 'la', 'j', 'avais', 'vite', 'compris', 'qu', 'il', 'n', 'e', 'tais', 'pas', 'plus', 'cure', 'que', 'moi', 'surtout', 'quand', 'je', 'l', 'ai', 'vu', 'avec', 'une', 'belle', 'jeune', 'demoiselle', 'qui', 'ne', 'comprenait', 'gue', 're', 'le', 'wallon', 'mais', 'qui', 'e', 'tait', 'bien', 'de', 'cide', 'e', 'a', 'l', 'apprendre', 'avec', 'des', 'professeurs', 'comme', 'pierrot', 'comme', 'jeannot', 'comme', 'roger', 'ou', 'comme', 'moi', 'dit', 'il', 'le', 'fou', 'there', 'were', 'some', 'uncertainties', 'and', 'disagreements', 'i', 've', 'gone', 'with', 'the', 'majority', 'view', 'in', 'each', 'case', 'the', 'biggest', 'problem', 'was', 'the', 'very', 'last', 'bit', 'which', 'caused', 'havoc', 'though', 'the', 'gist', 'of', 'it', 'seems', 'generally', 'clear', 'there', 'was', 'some', 'disagreement', 'as', 'to', 'whether', 'it', 'was', 'the', 'non', 'priest', 'or', 'the', 'young', 'girl', 'who', 'wanted', 'to', 'learn', 'walloon', 'most', 'people', 'went', 'for', 'the', 'woman', 'which', 'is', 'what', 'the', 'syntax', 'appears', 'to', 'say', 'the', 'strange', 'form', 'rawa', 'rdo', 'in', 'the', 'second', 'line', 'appears', 'to', 'be', 'the', 'same', 'word', 'as', 'french', 'regarder', 'but', 'i', 'am', 'told', 'that', 'in', 'northern', 'dialects', 'this', 'word', 'is', 'widely', 'used', 'in', 'the', 'sense', 'of', 'wait', 'wait', 'for', 'watch', 'for', 'another', 'headache', 'was', 'the', 'word', 'bwe', 'ce', 'le', 'in', 'line', 'this', 'clearly', 'means', 'something', 'like', 'demoiselle', 'and', 'it', 'is', 'possibly', 'the', 'same', 'word', 'as', 'french', 'pucelle', 'virgin', 'maiden', 'which', 'is', 'unlikely', 'to', 'be', 'the', 'sense', 'intended', 'i', 'am', 'told', 'that', 'speakers', 'of', 'walloon', 'are', 'now', 'generally', 'elderly', 'apart', 'from', 'some', 'younger', 'people', 'who', 'are', 'enthusiasts', 'though', 'the', 'belgian', 'student', 'i', 'consulted', 'here', 'told', 'me', 'she', 'had', 'a', 'friend', 'who', 'spoke', 'walloon', 'some', 'younger', 'people', 'of', 'limited', 'education', 'are', 'also', 'said', 'to', 'have', 'a', 'grasp', 'of', 'the', 'variety', 'and', 'engagingly', 'i', 'am', 'told', 'that', 'obscenities', 'and', 'insults', 'tend', 'to', 'persist', 'especially', 'well', 'one', 'respondent', 'objected', 'to', 'my', 'speaking', 'of', 'walloon', 'as', 'a', 'dialect', 'of', 'french', 'preferring', 'to', 'see', 'it', 'as', 'a', 'distinct', 'language', 'here', 's', 'an', 'english', 'version', 'it', 's', 'fifteen', 'years', 'ago', 'now', 'i', 'was', 'at', 'the', 'albert', 'leonard', 'institute', 'and', 'i', 'was', 'curious', 'because', 'i', 'had', 'been', 'told', 'that', 'a', 'teacher', 'from', 'the', 'seminary', 'wanted', 'to', 'see', 'us', 'to', 'talk', 'about', 'walloon', 'i', 'still', 'remember', 'what', 'i', 'was', 'wondering', 'at', 'that', 'moment', 'so', 'how', 'old', 'is', 'that', 'priest', 'i', 'quickly', 'understood', 'that', 'he', 'was', 'no', 'more', 'a', 'priest', 'than', 'i', 'was', 'particularly', 'when', 'i', 'saw', 'him', 'with', 'a', 'beautiful', 'young', 'girl', 'who', 'scarcely', 'knew', 'any', 'walloon', 'but', 'who', 'was', 'determined', 'to', 'learn', 'it', 'from', 'teachers', 'like', 'pierrot', 'like', 'jannot', 'like', 'roger', 'or', 'like', 'me', 'that', 's', 'what', 'he', 'said', 'the', 'fool', 'the', 'passage', 'was', 'written', 'by', 'm', 'georges', 'pasau', 'pre', 's', 'ident', 'du', 'muse', 'e', 'de', 'la', 'parole', 'au', 'pays', 'de', 'bastogne', 'it', 'appeared', 'in', 'issue', 'of', 'the', 'magazine', 'singuliers', 'which', 'is', 'devoted', 'to', 'walloon', 'this', 'was', 'a', 'special', 'number', 'given', 'over', 'to', 'the', 'publication', 'of', 'a', 'new', 'dictionary', 'of', 'walloon', 'the', 'dictionary', 'is', 'michel', 'francard', 'dictionnaire', 'des', 'parlers', 'wallons', 'du', 'pays', 'de', 'bastogne', 'brussels', 'deboeck', 'universite', 'isbn', 'francard', 'is', 'professor', 'of', 'romance', 'linguistics', 'at', 'the', 'university', 'of', 'louvain', 'in', 'belgium', 'his', 'address', 'is', 'faculte', 'des', 'lettres', 'universite', 'catholique', 'de', 'louvain', 'louvain', 'le', 'nauve', 'belgium', 'and', 'his', 'e', 'mail', 'is', 'francard', 'frwa', 'ucl', 'ac', 'be', 'i', 'have', 'n', 't', 'consulted', 'him', 'yet', 'but', 'plan', 'to', 'do', 'so', 'the', 'orthography', 'used', 'here', 'for', 'walloon', 'was', 'i', 'believe', 'invented', 'by', 'francard', 'specifically', 'for', 'the', 'dictionary', 'the', 'dictionary', 'contains', 'some', 'nice', 'dialect', 'maps', 'and', 'some', 'linguistic', 'information', 'about', 'walloon', 'my', 'thanks', 'to', 'jean', 'francois', 'carrasco', 'richard', 'coates', 'jean', 'francois', 'delannoy', 'roger', 'feron', 'frederik', 'fouvry', 'vincent', 'granville', 'ted', 'harding', 'yolande', 'meessen', 'philippe', 'mennecier', 'bernd', 'moebius', 'and', 'his', 'mother', 'joseph', 'reisdoerfer', 'thierry', 'j', 'van', 'steenberghe', 'guido', 'vanden', 'wyngaerd', 'and', 'max', 'wheeler', 'larry', 'trask', 'cogs', 'university', 'of', 'sussex', 'brighton', 'bn', 'qh', 'england', 'larryt', 'cogs', 'susx', 'ac', 'uk'], 0]\n",
      "[['Subject', 'coling', 'acl', 'registration', 'deadline', 'early', 'registration', 'for', 'coling', 'acl', 'ends', 'july', 'to', 'benefit', 'from', 'reduced', 'rates', 'your', 'registration', 'form', 'and', 'your', 'payment', 'must', 'be', 'received', 'by', 'that', 'date', 'for', 'further', 'information', 'on', 'the', 'conference', 'and', 'on', 'how', 'to', 'register', 'consult', 'the', 'conference', 'web', 'site', 'at', 'http', 'coling', 'acl', 'iro', 'umontreal', 'ca'], 0]\n"
     ]
    }
   ],
   "source": [
    "# 测试是否移除标点符号\n",
    "print(train_data[0])\n",
    "print(test_data[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 实现 Spam Detector"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import reduce\n",
    "def Symbols(data):\n",
    "    # 提取字母表\n",
    "    V = []\n",
    "    for e in data:\n",
    "        mail = e[0]\n",
    "        label_ = e[1]\n",
    "        for symbol in mail:\n",
    "            if symbol in V:\n",
    "                pass\n",
    "            else:\n",
    "                V.append(symbol)\n",
    "    return V\n",
    "\n",
    "def Count(data,label):\n",
    "    # 特定label的元素\n",
    "    D = []\n",
    "    for e in data:\n",
    "        data_ = e[0]\n",
    "        label_ = e[1]\n",
    "        if label == label_:\n",
    "            D.append(data_)\n",
    "    return D\n",
    "        \n",
    "class SpamDetector(object):\n",
    "    def __init__(self):\n",
    "        # 先验概率\n",
    "        self.P0 = None\n",
    "        self.P1 = None\n",
    "        # 后验概率\n",
    "        self.P = {}\n",
    "        # 词汇表 \n",
    "        self.V = []\n",
    "    \n",
    "    def train(self, train_data):\n",
    "        # (1) 计算单词空间\n",
    "        print('On computing alphabet...')\n",
    "        self.V = Symbols(train_data)\n",
    "        # (2) 计算先验概率\n",
    "        print('On computing prior prob...')\n",
    "        D0 = Count(train_data,0)\n",
    "        D1 = Count(train_data,1)\n",
    "        self.P0 = len(D0) / len(train_data)\n",
    "        self.P1 = len(D1) / len(train_data)\n",
    "        # (3) 计算 Tc\n",
    "        T0 = np.array(reduce(lambda x,y:x+y, D0))\n",
    "        T1 = np.array(reduce(lambda x,y:x+y, D1))\n",
    "        n0 = len(T0)\n",
    "        n1 = len(T1)\n",
    "        # (4) 计算后验概率\n",
    "        print('On computing posterior prob...')\n",
    "        for word in self.V:\n",
    "            n0k = np.sum((T0==word) + 0)\n",
    "            n1k = np.sum((T1==word) + 0)\n",
    "            self.P[word+'0'] = (n0k + 1) / (n0 + len(self.V))\n",
    "            self.P[word+'1'] = (n1k + 1) / (n1 + len(self.V))\n",
    "    \n",
    "    def test(self, test_datas):\n",
    "        pred_y = []\n",
    "        print('On computing test...')\n",
    "        for e in test_datas:\n",
    "            data = e[0]\n",
    "            L = []\n",
    "            for word in data:\n",
    "                if word in self.V:\n",
    "                    L.append(word)\n",
    "            # 使用对数，防止过小造成数据溢出\n",
    "            y0 = y1 = 0\n",
    "            for word in L:\n",
    "                y0 += np.log(self.P[word+'0'])\n",
    "                y1 += np.log(self.P[word+'1'])\n",
    "            y0 += np.log(self.P0)\n",
    "            y1 += np.log(self.P1)\n",
    "            # print(y0, y1)\n",
    "            pred_y.append(0 if y0 > y1 else 1)\n",
    "        return pred_y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "On computing alphabet...\n",
      "On computing prior prob...\n",
      "On computing posterior prob...\n",
      "On computing test...\n",
      "-1971.5296502484782 -2144.036376484316\n",
      "-4138.519636406701 -4337.847620800747\n",
      "-1515.0466159418008 -1753.4748329346592\n",
      "-10261.273124773159 -11017.087941777632\n",
      "-1217.4172478081896 -1102.7152691495353\n",
      "-5120.741373166871 -5663.268844685511\n",
      "-3026.7392532810873 -3169.1897737663808\n",
      "-2506.039047256746 -2757.306054240056\n",
      "-2796.3257749965032 -3118.868487747341\n",
      "-3927.536335233278 -4410.240634250426\n",
      "-1370.1052849002836 -1479.6735238195593\n",
      "-460.9985865152019 -396.38715621363394\n",
      "-6220.38607430793 -7017.965107145195\n",
      "-3989.363026725769 -4555.3705548164035\n",
      "-3020.2876966915314 -3270.3770567361935\n",
      "-2938.4876341387276 -3280.915011187921\n",
      "-2353.3595919413788 -2636.085135727335\n",
      "-619.7056787666382 -582.9532599669438\n",
      "-1823.6150522334915 -2118.0351603285108\n",
      "-948.3982426810526 -871.9988770410815\n",
      "-4250.428435593877 -4733.99150503562\n",
      "-1500.475081513769 -1344.3898526201103\n",
      "-1780.6702833695354 -2052.0158328316265\n",
      "-5155.571508161837 -5730.510419043183\n",
      "-7496.776207749929 -8263.349818635623\n",
      "-1166.851946767787 -1310.8261868256618\n",
      "-4975.319047470392 -5398.737052592474\n",
      "-1563.0914735014412 -1779.4170114419762\n",
      "-2217.586596273956 -2528.000924311623\n",
      "-6499.537513999698 -6958.053793177319\n",
      "-6612.869420899525 -7081.518887194263\n",
      "-6691.14468675601 -7158.076362351045\n",
      "-2887.847865539772 -3273.612284703846\n",
      "-12045.858800930446 -13035.644211832792\n",
      "-557.5757674013217 -609.5408036982863\n",
      "-4788.315825394576 -5361.874243508596\n",
      "-2219.458345021558 -2460.3053001250487\n",
      "-736.652439426806 -664.0956504368585\n",
      "-3934.8005297374616 -4439.21134873305\n",
      "-1513.8599130313019 -1730.2061131465991\n",
      "-727.0130080055715 -661.2410733139611\n",
      "-6659.3872879728615 -7571.6775755535455\n",
      "-2635.2950481985213 -3025.7592763484813\n",
      "-1580.3423225207396 -1758.3316950049523\n",
      "-4153.230839312303 -4903.253649983175\n",
      "-810.1110050131597 -949.1197463987005\n",
      "-10381.444664871444 -11272.876525474117\n",
      "-2031.738733294754 -2292.929515811897\n",
      "-2099.6958715581277 -1976.859545312707\n",
      "-4177.9414957696545 -4695.37705595068\n",
      "-8126.214147472356 -9107.711760571367\n",
      "-1952.0038224621933 -2195.9453983069775\n",
      "-1686.8360952830901 -1848.749681703205\n",
      "-2006.3337281750864 -2234.632124031058\n",
      "-466.5174491433832 -531.4447208477577\n",
      "-3629.405251310842 -3425.309146231023\n",
      "-7323.666097948124 -7948.919202994991\n",
      "-585.354270907159 -654.1896408279669\n",
      "-1248.8394614718734 -1366.0215424512369\n",
      "-1704.710995469323 -1870.1450191922725\n",
      "-821.2765432262156 -756.6188437095522\n",
      "-4921.411066059084 -5719.0736564800945\n",
      "-2444.827493447449 -2796.2105633223955\n",
      "-3544.4978126093265 -4008.7614760048386\n",
      "-764.2614358431863 -831.2281010535042\n",
      "-2103.4289490772426 -2377.4143484386273\n",
      "-7226.788529495804 -7955.509635917105\n",
      "-1718.6101649711015 -2002.002903988038\n",
      "-576.774505517139 -531.3569763017808\n",
      "-1939.8883187016734 -2143.1914234991955\n",
      "-6126.634503822092 -6762.1462281320455\n",
      "-115.72264315871357 -115.21723684700235\n",
      "-2915.0631433588323 -3207.362447728232\n",
      "-759.5864807284853 -738.3214165134948\n",
      "-775.6178010244444 -862.9240441506626\n",
      "-6893.983568742829 -7578.181439745216\n",
      "-1124.6560217493438 -1196.1059778137449\n",
      "-4370.559640213963 -4307.227345056877\n",
      "-820.3580173063193 -750.959499683738\n",
      "-244.79275190920893 -275.674892394853\n",
      "-1131.068793666196 -1032.1355137968653\n",
      "-10397.678601559315 -11288.504875906672\n",
      "-942.4181735012575 -1041.794057367939\n",
      "-2838.4677515081635 -3310.7618403507145\n",
      "-15742.94393317562 -14983.85591700352\n",
      "-2192.520742205975 -2576.0860549229296\n",
      "-6893.983568742829 -7578.181439745216\n",
      "-7659.009454901008 -8257.457372122386\n",
      "-976.4153005480423 -1155.9054168872515\n",
      "-944.7381954856569 -867.6277768433838\n",
      "-4346.029003170329 -4785.606991859154\n",
      "-679.5322020280742 -768.70845688961\n",
      "-586.3689380512752 -531.0847644691829\n",
      "-749.968387181089 -876.4255771336947\n",
      "-1314.8281536462234 -1358.1882886000699\n",
      "-2055.2145654739593 -2256.862611141513\n",
      "-357.4500783919566 -382.5897473214454\n",
      "-3405.8476548632266 -3641.816779407329\n",
      "-3151.6542459389766 -3553.8273884303044\n",
      "-5030.062577356761 -4792.8888211893545\n",
      "-1848.967015858209 -1752.6734363966268\n",
      "-6315.456708973518 -7020.795001661586\n",
      "-1230.4076231666934 -1402.3995682114664\n",
      "-5039.36660179055 -5631.062817582368\n",
      "-2612.187441461498 -3105.762740471849\n",
      "-4212.579194233993 -4693.297396217234\n",
      "-4267.388742493368 -4657.654772324303\n",
      "-12079.794136919138 -13219.810037750925\n",
      "-5278.228806048636 -5755.273492310572\n",
      "-2939.7112223746462 -3356.302381009825\n",
      "-2268.5654503543574 -2507.259645026501\n",
      "-2064.616539763966 -1901.3283001374084\n",
      "-7781.045703672047 -8356.71652773421\n",
      "-389.3664140647496 -451.47981126031306\n",
      "-2758.3683151106425 -3017.732266383749\n",
      "-1335.6562119714652 -1530.3466284504127\n",
      "-5897.0607961690575 -6770.1644150894035\n",
      "-2662.196089900905 -3004.863665511796\n",
      "-957.0669411587428 -1067.3729471860488\n",
      "-1652.1023254441204 -1907.2421602722536\n",
      "-7778.569850421027 -8686.996651785288\n",
      "-3817.9883842672975 -4278.635607914137\n",
      "-5924.513607628078 -6880.01060687653\n",
      "-1569.9262708211709 -1794.6931775244177\n",
      "-1951.4981629127062 -2216.4339183494885\n",
      "-5701.345242938048 -6408.963487604606\n",
      "-4574.644968872153 -4854.851858118583\n",
      "-650.7163114484447 -772.7074831378453\n",
      "-7525.897706293807 -8637.43831989989\n",
      "-3505.373349680183 -3157.333389581123\n",
      "-3321.3025613479404 -3707.26121731501\n",
      "-6810.907292380699 -7327.565664096852\n",
      "-8252.168195453334 -9099.799228219494\n",
      "-4816.604574254853 -5279.142069875111\n",
      "-1577.2475588719421 -1741.7344930157658\n",
      "-2226.829187181169 -2454.6131728039873\n",
      "-3000.096872338988 -3339.845894732581\n",
      "-4520.0650522184305 -4984.092585840049\n",
      "-5548.706147734136 -5239.4249149335565\n",
      "-1110.9083547959015 -1208.0251322337288\n",
      "-3095.3760773793324 -3505.1553687817145\n",
      "-858.8078328033198 -758.6519882182029\n",
      "-1956.1760275006307 -2095.2290866080248\n",
      "-4689.827484365907 -4463.789723967125\n",
      "-1054.2388230753006 -1107.5516641513882\n",
      "-630.0968271522571 -602.6558664291564\n",
      "-26301.234704411294 -28672.544158213666\n",
      "-5267.92508719196 -5980.87126408821\n",
      "-1511.986190993401 -1709.8925835871707\n",
      "-3180.2777698335517 -3555.3812485621615\n",
      "-5007.577548577059 -5565.207672191967\n",
      "-1219.2704741913337 -1318.5931657591204\n",
      "-4698.819413933086 -5095.896582974195\n",
      "-2380.31506530253 -2678.1289123159545\n",
      "-1074.54603330813 -1157.2682639628538\n",
      "-1576.9339730847587 -1738.253104223978\n",
      "-1268.4644542248095 -1501.0827385176835\n",
      "-1918.7764374678447 -2158.594931409791\n",
      "-9833.86110128725 -10405.555816909724\n",
      "-425.4932796227475 -455.6920445037705\n",
      "-1505.651410091554 -1423.9659150950372\n",
      "-5102.070145384991 -5670.239557200457\n",
      "-1723.4524553109645 -1979.5278122144603\n",
      "-5086.6607322560185 -5638.928215199711\n",
      "-7220.572552845569 -8035.204977756849\n",
      "-1931.4622492969615 -2181.528585448234\n",
      "-525.7243742361504 -496.1064481603922\n",
      "-8234.997401998851 -7434.008411798459\n",
      "-3695.0351635051875 -3989.958668544102\n",
      "-3855.59183941622 -4272.997038282179\n",
      "-3804.695815833111 -4290.199127456667\n",
      "-1482.5572199745945 -1700.5951379853725\n",
      "-1635.448540536768 -1789.454625009646\n",
      "-1906.117553329383 -2082.3991123153132\n",
      "-836.9631371889421 -942.102339996515\n",
      "-4506.555777399362 -4274.40800425683\n",
      "-502.10362977504803 -566.0521674429979\n",
      "-6978.9286800580385 -7912.662639124443\n",
      "-678.57158671563 -682.2078631624638\n",
      "-4311.135009378384 -4733.81742149483\n",
      "-8952.981725059648 -8366.52185174366\n",
      "-4123.329821084796 -4698.98247566063\n",
      "-2009.212816035426 -2119.946677315694\n",
      "-1331.0625020328814 -1531.384746810696\n",
      "-1651.3006224194044 -1833.2691023029747\n",
      "-1773.6379351545825 -1996.301518145294\n",
      "-2670.19067169146 -3069.282423371234\n",
      "-978.4069265296334 -1127.1648020409489\n",
      "-1082.9933013272625 -1199.5748148692855\n",
      "-2938.8370559667655 -3259.9179503843066\n",
      "-2512.8042738661134 -2843.394404059409\n",
      "-1017.817020742209 -1162.30160532395\n",
      "-1643.2520366973758 -1782.9578376037307\n",
      "-2139.1723241586647 -2388.219078252921\n",
      "-573.3243969144087 -655.0200592162346\n",
      "-299.569808377863 -280.6977127261179\n",
      "-1217.4172478081896 -1102.7152691495353\n",
      "-1622.9958071383837 -1546.7522743739196\n",
      "-5444.855164677453 -6098.758093290124\n",
      "-1312.065897313603 -1435.842445779489\n",
      "-3814.379800772759 -4257.741823122691\n",
      "-7220.087679389143 -7828.175899486282\n",
      "-9056.30781301608 -10380.025493629639\n",
      "-5287.8196303335735 -5909.329538488599\n",
      "-2132.0627365301593 -2469.620284422544\n",
      "-3922.1540209521518 -4398.619617003105\n",
      "-9552.756782405642 -10652.484594109266\n",
      "-1346.9475932457563 -1498.875091290654\n",
      "-1498.1439560131498 -1706.8239803485858\n",
      "-4609.777150403768 -5217.630476134684\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-9949.025347845198 -10606.852600737117\n",
      "-8799.856621035227 -9588.02996117425\n",
      "-5040.51787503751 -5566.8350653206935\n",
      "-534.7531349548907 -518.2879430715474\n",
      "-286.2197836614638 -256.0908526682496\n",
      "-3284.895452979438 -3749.938933887972\n",
      "-1674.710649429015 -1990.4262825505725\n",
      "-3136.488549735512 -3334.47828319801\n",
      "-11972.14523180672 -13239.832509993304\n",
      "-2465.7579328781144 -2892.1658736169898\n",
      "-5635.576223108932 -6610.503314580141\n",
      "-2620.3718664434705 -2939.9013950037884\n",
      "-1100.6927614302983 -1251.3880365224422\n",
      "-3963.79731405679 -3646.2082903826717\n",
      "-7345.159986743661 -6857.750210322111\n",
      "-1156.5447616266101 -1325.3773527120877\n",
      "-1364.4051679582326 -1560.0496512570592\n",
      "-2429.656304384094 -2706.1342810921656\n",
      "-1920.504611180246 -2121.5588269169875\n",
      "-2774.726770009598 -3041.7854112301625\n",
      "-2313.483565989512 -2633.7454180454483\n",
      "-1803.9891018288633 -2086.8744158186937\n",
      "-2312.1466645130495 -2685.022388382248\n",
      "-386.9356378496065 -393.827341037822\n",
      "-917.8806941867127 -981.4903915854169\n",
      "-3065.637054939802 -3523.7196002564638\n",
      "-801.905656910981 -733.1003272567418\n",
      "-1474.046506731698 -1695.9300817318817\n",
      "-556.4347535497277 -508.9277278411461\n",
      "-604.2172298893405 -544.3436924830128\n",
      "-7828.883741355152 -8836.180939245342\n",
      "-524.5890819109127 -481.06797592056705\n",
      "-7495.4523989642485 -8128.912626506165\n",
      "-806.8740628124787 -932.7944916344794\n",
      "-2222.056984154247 -2446.197745116417\n",
      "-11385.582220652273 -12218.693432463691\n",
      "-2096.761096302743 -2354.599281834434\n",
      "-740.9358041322292 -843.0247174898795\n",
      "-3550.633429434561 -3795.6564377904547\n",
      "-4303.324597349557 -4722.963370328078\n",
      "-2906.5611491204877 -3296.7272636929274\n",
      "-5204.344357190714 -5559.594857394141\n",
      "-2263.8268049256576 -2577.7596936731734\n",
      "-1159.515915691672 -1286.1969223090573\n",
      "-5981.773097225041 -6564.7751192759415\n",
      "-2095.1965111284712 -2271.034293289261\n",
      "-763.4630254447386 -704.4002401576853\n",
      "-2497.1023136834915 -2571.847214708819\n",
      "-9982.479786219632 -11419.663604136838\n",
      "-3828.3128355790527 -4383.533523890509\n",
      "-4502.417705709677 -4367.463548575448\n",
      "-13469.992865085647 -14500.2702370169\n",
      "-1269.9308836558553 -1478.8003021650509\n",
      "-722.7419541665831 -855.0217068596546\n",
      "-2081.9156572414895 -2325.4788036875\n",
      "-7273.924100540991 -7862.644029424796\n",
      "-1837.7311641221927 -2006.174806542523\n",
      "-1230.6016629538174 -1344.3889458690287\n",
      "-1954.2998228740496 -2124.6861622877846\n",
      "-3175.4581700194963 -3490.280352872371\n",
      "-834.6353882099238 -733.8727849867919\n",
      "-1815.7959253310094 -2119.9842626881373\n",
      "-9079.547027747158 -10397.743030107298\n",
      "-3237.5537439015675 -3555.8991800374697\n",
      "-5787.039382572983 -6351.381271211846\n",
      "-30964.602951479283 -34018.716206738936\n",
      "-6054.752132947874 -6405.916253650234\n",
      "-6051.206452728245 -6725.31210640827\n",
      "-5263.648991520977 -6025.047500676776\n",
      "-2864.1891935005756 -3332.2628660954397\n",
      "-1089.8312067889572 -1202.7889337802806\n",
      "-1165.08978066871 -1333.4914759110306\n",
      "-5452.8163467824925 -6199.140219097137\n",
      "-15049.66068405012 -16467.983010434044\n",
      "-1065.7759773762102 -1221.2628415799934\n",
      "-6433.170757629722 -6967.686787017106\n",
      "-696.0061057230369 -790.5742933411992\n",
      "-1800.6546818643521 -1882.5251178346764\n",
      "-4533.571606180525 -4262.637103633183\n",
      "-7853.8043135930975 -8665.059968015035\n",
      "-4068.426654583097 -4662.028833261903\n"
     ]
    }
   ],
   "source": [
    "# 训练 naive bayes\n",
    "detector = SpamDetector()\n",
    "detector.train(train_data)\n",
    "pred_y = detector.test(test_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>accuracy</th>\n",
       "      <td>0.993127</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>precision</th>\n",
       "      <td>1.000000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>recall</th>\n",
       "      <td>0.959184</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>F-score</th>\n",
       "      <td>0.979167</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              Value\n",
       "accuracy   0.993127\n",
       "precision  1.000000\n",
       "recall     0.959184\n",
       "F-score    0.979167"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 计算几个正确性的参数\n",
    "import pandas as pd\n",
    "tp = 0\n",
    "tn = 0\n",
    "fp = 0\n",
    "fn = 0\n",
    "for i in range(0,len(test_data)):\n",
    "    if test_data[i][1] == 1 and pred_y[i] == 1:\n",
    "        tp += 1\n",
    "    elif test_data[i][1] == 1 and pred_y[i] == 0:\n",
    "        fn += 1\n",
    "    elif test_data[i][1] == 0 and pred_y[i] == 1:\n",
    "        fp += 1\n",
    "    elif test_data[i][1] == 0 and pred_y[i] == 0:\n",
    "        tn += 1\n",
    "\n",
    "accuracy = (tp + tn) / (tp + tn + fp + fn)\n",
    "precision = tp / (tp + fp)\n",
    "recall = tp / (tp + fn)\n",
    "fscore = 2 / (1 / precision + 1 / recall)\n",
    "df = pd.DataFrame(\n",
    "    {'Value':[accuracy, precision,recall,fscore]},\n",
    "    index = ['accuracy','precision','recall','F-score']\n",
    ")\n",
    "df.to_csv('Result.csv')\n",
    "df\n",
    "# print(\n",
    "#     'accuracy:\\t%s\\n' % accuracy,\n",
    "#     'precision:\\t%s\\n' % precision,\n",
    "#     'recall:\\t%s\\n' % recall,\n",
    "#     'F-score:\\t%s\\n' % fscore\n",
    "# )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "torch",
   "language": "python",
   "name": "torch"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
